<template>
  <div>
    <el-form :label-width="100">
      <el-form-item label="SPU名称">
        <el-input
          placeholder="请输入 SPU名称"
          v-model="formData.spuName"
        ></el-input>
      </el-form-item>

      <el-form-item label="品牌">
        <el-select v-model="formData.tmId">
          <el-option
            v-for="tm in trademarks"
            :key="tm.id"
            :label="tm.tmName"
            :value="tm.id"
          ></el-option>
        </el-select>
      </el-form-item>

      <el-form-item label="SPU描述">
        <el-input
          type="textarea"
          :rows="3"
          placeholder="请输入 SPU描述"
          v-model="formData.description"
        />
      </el-form-item>
      <!--list-type: 文件列表的类型，支持：'text' | 'picture' | 'picture-card'
      on-preview: 点击图片预览触发的钩子-->

      <el-form-item label="SPU图片">
        <el-upload
          class="uploader"
          :action="uploadUrl"
          list-type="picture-card"
          :on-success="onSuccessHandler"
          :on-preview="onPreviewHandler"
          :on-remove="onRemoveHandler"
          :file-list="fileList"
        >
          <el-icon class="uploader-icon"><ele-Plus></ele-Plus></el-icon>
        </el-upload>
      </el-form-item>

      <el-form-item label="销售属性">
        <div style="margin-bottom: 20px">
          <el-select
            v-model="selectedBaseSaleAttr"
            :placeholder="`还有 ${unusedBaseSaleAttrs.length} 个未选择`"
            :disabled="unusedBaseSaleAttrs.length == 0"
          >
            <el-option
              v-for="item in unusedBaseSaleAttrs"
              :key="item.id"
              :label="item.name"
              :value="item.id + '|' + item.name"
            ></el-option>
          </el-select>
          <el-button
            style="margin-left: 10px"
            type="primary"
            @click="addBaseSaleAttrHandler"
            :disabled="unusedBaseSaleAttrs.length == 0"
            >添加销售属性</el-button
          >
        </div>
        <el-table border stripe :data="formData.spuSaleAttrList">
          <el-table-column :width="80" label="序号" type="index">
          </el-table-column>
          <el-table-column
            :width="150"
            label="属性名"
            prop="saleAttrName"
          ></el-table-column>
          <el-table-column label="属性值名称列表">
            <template #="{ row }">
              <!-- 显示已经添加到值的列表 -->
              <el-tag
                v-for="(item, index) in row.spuSaleAttrValueList"
                :key="index"
                style="margin-right: 10px"
                closable
                @close="
                  removeSaleAttrValueHandler(row.spuSaleAttrValueList, index)
                "
                >{{ item.saleAttrValueName }}
              </el-tag>

              <el-input
                style="width: 50px"
                v-if="row.isEdit"
                ref="editInputRef"
                @blur="enterSaleAttrName(row)"
                @keydown.enter="enterSaleAttrName(row)"
                v-model="inputSaleAttrValue"
              />
              <el-button v-else @click="changeEditStatus(row)">添加</el-button>
            </template>
          </el-table-column>
          <el-table-column :width="150" label="操作">
            <template #="{ row }">
              <el-button
                icon="ele-Delete"
                type="danger"
                @click="removeSaleAttr(row)"
              ></el-button>
            </template>
          </el-table-column>
        </el-table>
      </el-form-item>

      <el-form-item>
        <el-button type="primary" @click="saveSPUHandler">保存</el-button>
        <!--去列表页面-->
        <el-button type="primary" @click="changeViewHandler">取消</el-button>
      </el-form-item>
    </el-form>

    <el-dialog
      width="80%"
      v-model="isShowPreviewDialog"
      :title="previewImg.name"
    >
      <img style="width: 100%; height: 100%" :src="previewImg.url" alt="img" />
      <!-- <el-carousel indicator-position="outside" style="height: 500px">
       <el-carousel-item
         v-for="item in formData.spuImageList"
         :key="item.imgUrl"
         style="height: 500px"
       >
         <img style="width: 100%; height: 500px" :src="item.imgUrl" />
       </el-carousel-item>
     </el-carousel> -->
    </el-dialog>
  </div>
</template>

<script lang="ts">
import { defineComponent } from "vue";

export default defineComponent({
  name: "SPUForm",
});
</script>

<script setup lang="ts">
import type {
  IAddSPU,
  ISPUSaleAttr,
  ISPU,
  ISPUImage,
  ISPUSaleAttrValue,
  IUpdateSPU,
} from "@/api/spu";
import VIEW_TYPE from "@/views/product/spu/vueTypes";
import { computed, nextTick, ref } from "vue";
import { useCategorySelectorStore } from "@/stores/categorySelector";
import { storeToRefs } from "pinia";
import type { IBaseTrademark } from "@/api/trademark";
import { ElMessage, ElMessageBox } from "element-plus";
import type { UploadFile, UploadUserFile } from "element-plus";
import * as tmapis from "@/api/trademark";
import type { IBaseSaleAttr } from "@/api/attr";
import * as attrApis from "@/api/attr";
import * as apis from "@/api/spu";
//获取仓库中的category3Id
const { category3Id } = storeToRefs(useCategorySelectorStore());
// 定义一个变量用于收集提交的时候所需要的数据，并初始化
type IFormDataSPUSaleAttr = ISPUSaleAttr & { isEdit?: boolean };
type FormData = Omit<ISPU, "id"> & {
  id?: number;
  // SPU 图片列表
  spuImageList: ISPUImage[];
  // SPU 销售属性和值的列表
  spuSaleAttrList: IFormDataSPUSaleAttr[];
};
const formData = ref<FormData>({
  category3Id: category3Id.value as number,
  tmId: 1,
  spuName: "",
  description: "",
  spuImageList: [],
  spuSaleAttrList: [],
});

//定义接收的外部 props
const props = defineProps<{
  data?: ISPU;
}>();
// console.log("props", props.data);

//定义一个变量用于转换后端spuimagelist的数据格式，适应 upload 组件所需的格式
if (props.data) {
  formData.value.id = props.data.id;
  formData.value.category3Id = props.data.category3Id as number;
  formData.value.spuName = props.data.spuName as string;
  formData.value.tmId = props.data.tmId as number;
  formData.value.description = props.data.description as string;
  // 获取当前spu的图片列表
  getImageList(props.data.id);
  // 获取当前spu的销售属性列表数据
  getSaleAttrList(props.data.id);
}

const fileList = ref<UploadUserFile[]>([]);
//存储trademarks
const trademarks = ref<IBaseTrademark[]>([]);

//存储用户选择的基础销售属性数据
const selectedBaseSaleAttr = ref("");

// 存储编辑状态下的input实例
const editInputRef = ref<HTMLInputElement>();

//保存用户在属性值input上输入的内容
const inputSaleAttrValue = ref("");

//定义事件
const emits = defineEmits(["change-view"]);

//上传文件的api地址
const uploadUrl = `${import.meta.env.VITE_API_URL}/product/upload`;

//图片预览的对话框状态
const isShowPreviewDialog = ref(false);

//当前需要预览的图片信息
const previewImg = ref({
  name: "",
  url: "",
});

//获取指定id下的图片列表
async function getImageList(id: number) {
  try {
    formData.value.spuImageList = await apis.requestSPUImageList(id);
    // 把数据转换一下赋值给 fileList
    fileList.value = formData.value.spuImageList.map((item) => {
      return {
        name: item.imgName,
        url: item.imgUrl,
      };
    });
  } catch (e) {
    ElMessage.error("获取图片列表数据失败");
  }
}

//获取指定id下的销售属性列表
async function getSaleAttrList(id: number) {
  try {
    formData.value.spuSaleAttrList = await apis.requestSPUSaleAttrList(id);
  } catch (e) {
    ElMessage.error("获取销售属性列表数据失败");
  }
}

//存储基础销售属性列表
const baseSaleAttrs = ref<IBaseSaleAttr[]>([]);

//销售属性对应 el-select 中显示的并不是原始 baseSaleAttrs 数组
const unusedBaseSaleAttrs = computed(() => {
  // return baseSaleAttrs.value;
  const unused: IBaseSaleAttr[] = [];
  // 循环 baseSaleAttrs
  baseSaleAttrs.value.forEach((item) => {
    // 判断当前 item 是否在 formData.value.spuSaleAttrList 被使用了
    const isUsed = formData.value.spuSaleAttrList.find(
      (spuSaleAttr) => item.id === spuSaleAttr.baseSaleAttrId
    );
    // 如果 isUsed 为 true，表示 item 这条数据在 spuSaleAttrList 有对应的值，说明 item 这条数据已经被使用了
    if (!isUsed) {
      unused.push(item);
    }
  });
  return unused;
});

//
// 获取品牌列表数据
async function getTrademarks() {
  try {
    trademarks.value = await tmapis.requestBaseTrademarks();
  } catch (e) {
    ElMessage.error("品牌列表获取失败");
  }
}

//获取基础销售属性列表
async function getBaseSaleAttrs() {
  try {
    baseSaleAttrs.value = await attrApis.requestBaseSaleAttrList();
  } catch (e) {
    ElMessage.error("基础销售属性列表获取失败");
  }
}

//收集上传成功后的图片数据
function onSuccessHandler(response: { data: string }, uploadFile: UploadFile) {
  try {
    formData.value.spuImageList.push({
      imgName: uploadFile.name,
      imgUrl: response.data,
    });
  } catch (e) {
    ElMessage.error("上传图片失败");
  }
}

//
//点击图片预览
//uploadFile当前点击图片的数据
function onPreviewHandler(uploadFile: UploadFile) {
  // console.log(uploadFile);
  // 显示图片预览的对话框
  isShowPreviewDialog.value = true;
  previewImg.value = {
    name: uploadFile.name,
    url: (uploadFile.response as { data: string }).data,
  };
}

//当点击删除文件的时候
// uploadFile: 当前删除的文件信息
function onRemoveHandler(uploadFile: UploadFile) {
  // console.log(uploadFile);
  // 从 formData.spuImageList 数组中删除与 uploadFile 对应的数据
  formData.value.spuImageList = formData.value.spuImageList.filter(
    (item) => item.imgUrl !== (uploadFile.response as { data: string }).data
  );
}

//添加选择的基础销售属性
function addBaseSaleAttrHandler() {
  // console.log(selectedBaseSaleAttr.value);
  if (selectedBaseSaleAttr.value === "") {
    ElMessage.error("请选择一个基础销售属性");
  } else {
    // 在 formData.value.spuSaleAttrList 提交一条数据
    // selectedBaseSaleAttr.value = '1|颜色'
    const [id, name] = selectedBaseSaleAttr.value.split("|"); // [1,'颜色']
    formData.value.spuSaleAttrList.push({
      // 存储到其实就是当前用户选择的基础销售属性对应的id
      baseSaleAttrId: Number(id),
      // 存储到其实就是当前用户选择的基础销售属性对应的名称
      saleAttrName: name,
      spuSaleAttrValueList: [],
      // 使用一个 boolean 来标识当前输入对应的行是否为编辑状态
      isEdit: false,
    });
    // 清空这个变量，否则 select 中会显示这个变量的内容
    selectedBaseSaleAttr.value = "";
  }
}

//编辑按钮进入编辑状态
function changeEditStatus(row: IFormDataSPUSaleAttr) {
  row.isEdit = true;
  // 给当前input设置焦点
  nextTick(() => {
    editInputRef.value?.focus();
  });
}

//当编辑输入框失去焦点或按下回车键的时候
//当我们按下回车的时候，会执行两次 enterSaleAttrName
//- 原因：按下回车的时候，如果内容为空，就会设置 row.isEdit = false; 结果是让input被删除，导致失去了焦点，从而触发了两次事件：keydown、blur
//我们只需要判断一下当前这次函数执行的时候，row 的编辑状态是否为 false，如果为 false ，说明这次函数的执行事由于 keydown 触发重新渲染导致 失去焦点 执行了这一次函数
function enterSaleAttrName(row: IFormDataSPUSaleAttr) {
  // console.log(1, inputSaleAttrValue.value, row.isEdit);
  if (!row.isEdit) {
    // ElMessage.error("请输入内容");
    // row.isEdit = false;
    return;
  }
  // console.log(1);
  // 当输入的值不为空，才添加
  if (inputSaleAttrValue.value != "") {
    // 验证是否重复，把当前输入的值和row.spuSaleAttrValueList中已经存在的值进行验证
    // console.log(row.spuSaleAttrValueList);
    const isExists = row.spuSaleAttrValueList.find(
      (item) => item.saleAttrValueName == inputSaleAttrValue.value
    );
    // console.log(isExists);
    if (isExists) {
      // 取消编辑状态
      inputSaleAttrValue.value = "";
      row.isEdit = false;
      return ElMessage.error("输入值已经存在了");
    }
    // 向当前 row 中的 spuSaleAttrValueList 中添加一条数据
    row.spuSaleAttrValueList.push({
      // 来自于父级 row
      baseSaleAttrId: row.baseSaleAttrId,
      saleAttrName: row.saleAttrName,
      // 当前输入的内容
      saleAttrValueName: inputSaleAttrValue.value,
    });
    // 清空输入框中的内容
    inputSaleAttrValue.value = "";
  } else {
    ElMessage.error("请输入内容");
  }
  // 取消编辑状态
  row.isEdit = false;
}

//点击删除表格中指定的销售属性
async function removeSaleAttr(row: ISPUSaleAttr) {
  try {
    await ElMessageBox.confirm("你确定要删除吗？", "提示");

    // 把当前传入 row 从 formData.value.spuSaleAttrList 数组中删除掉
    formData.value.spuSaleAttrList = formData.value.spuSaleAttrList.filter(
      (item) => item != row
    );
  } catch (e) {}
}

//删除指定的属性值
function removeSaleAttrValueHandler(
  spuSaleAttrValueList: ISPUSaleAttrValue[],
  index: number
) {
  // 从 spuSaleAttrValueList 数组 删除 index 对应的值
  spuSaleAttrValueList.splice(index, 1);
}

//提交保存
async function saveSPUHandler() {
  // console.log(formData.value);

  try {
    // 去除一些不必要的数据
    // await apis.requestSaveSPUInfo({
    //   ...formData.value,
    //   spuImageList: formData.value.spuImageList,
    //   spuSaleAttrList: formData.value.spuSaleAttrList.map((item) => {
    //     return {
    //       baseSaleAttrId: item.baseSaleAttrId,
    //       saleAttrName: item.saleAttrName,
    //       spuSaleAttrValueList: item.spuSaleAttrValueList,
    //     };
    //   }),
    // });

    formData.value.spuSaleAttrList.forEach((item) => {
      delete item.isEdit;
    });

    if (formData.value.id) {
      // 编辑
      await apis.requestUpdateSPUInfo(formData.value as IUpdateSPU);
    } else {
      // 新增
      await apis.requestSaveSPUInfo(formData.value);
    }

    ElMessage.success("保存成功");
    // 返回列表页面
    emits("change-view", VIEW_TYPE.LIST);
  } catch (e) {
    ElMessage.error("保存失败");
  }
}

//取消 去列表页面
function changeViewHandler() {
  emits("change-view", VIEW_TYPE.LIST);
}

// 进入当前组件就获取 品牌列表数据
getTrademarks();
getBaseSaleAttrs();
</script>

<style scoped>
.uploader .thumb {
  width: 178px;
  height: 178px;
  display: block;
}
</style>

<style>
.uploader .el-upload {
  border: 1px dashed var(--el-border-color);
  border-radius: 6px;
  cursor: pointer;
  position: relative;
  overflow: hidden;
  transition: var(--el-transition-duration-fast);
}
.uploader .el-upload:hover {
  border-color: var(--el-color-primary);
}
.el-icon.uploader-icon {
  font-size: 28px;
  color: #8c939d;
  width: 178px;
  height: 178px;
  text-align: center;
}
</style>
